// <copyright file="ProductController.cs" company="EnterpriseApi">
// Copyright (c) EnterpriseApi. All rights reserved.
// </copyright>

using EnterpriseApi.DTOs;
using EnterpriseApi.Models;
using EnterpriseApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace EnterpriseApi.Controllers;

/// <summary>
/// 产品控制器，处理产品相关的HTTP请求
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
    private readonly IProductService _productService;
    private readonly ILogger<ProductController> _logger;

    /// <summary>
    /// 初始化ProductController的新实例
    /// </summary>
    /// <param name="productService">产品服务</param>
    /// <param name="logger">日志记录器</param>
    public ProductController(IProductService productService, ILogger<ProductController> logger)
    {
        _productService = productService ?? throw new ArgumentNullException(nameof(productService));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// 获取所有产品
    /// </summary>
    /// <returns>产品列表</returns>
    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult<IEnumerable<ProductDTO>>> GetAllProducts()
    {
        try
        {
            var products = await _productService.GetAllAsync();
            var productDTOs = products.Select(product => new ProductDTO
            {
                Id = product.Id,
                Name = product.Name,
                Description = product.Description,
                Price = product.Price,
                StockQuantity = product.StockQuantity,
                ImageUrl = product.ImageUrl,
                CreatedAt = product.CreatedAt,
                UpdatedAt = product.UpdatedAt,
                IsAvailable = product.IsAvailable,
                CategoryName = product.Category?.Name ?? "Unknown"
            });
            return Ok(productDTOs);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取所有产品时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "获取所有产品时发生错误");
        }
    }

    /// <summary>
    /// 根据ID获取产品
    /// </summary>
    /// <param name="id">产品ID</param>
    /// <returns>产品详情</returns>
    [HttpGet("{id}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<ProductDTO>> GetProductById(int id)
    {
        try
        {
            var product = await _productService.GetByIdAsync(id);
            if (product == null)
            {
                return NotFound();
            }

            var productDTO = new ProductDTO
            {
                Id = product.Id,
                Name = product.Name,
                Description = product.Description,
                Price = product.Price,
                StockQuantity = product.StockQuantity,
                ImageUrl = product.ImageUrl,
                CreatedAt = product.CreatedAt,
                UpdatedAt = product.UpdatedAt,
                IsAvailable = product.IsAvailable,
                CategoryName = product.Category?.Name ?? "Unknown"
            };
            return Ok(productDTO);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取产品详情时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "获取产品详情时发生错误");
        }
    }

    /// <summary>
    /// 创建新产品
    /// </summary>
    /// <param name="product">产品信息</param>
    /// <returns>创建的产品</returns>
    [HttpPost]
    [ProducesResponseType(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<ProductDTO>> CreateProduct([FromBody] Product product)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        try
        {
            product.CreatedAt = DateTime.UtcNow;
            product.UpdatedAt = DateTime.UtcNow;
            var createdProduct = await _productService.AddAsync(product);

            var productDTO = new ProductDTO
            {
                Id = createdProduct.Id,
                Name = createdProduct.Name,
                Description = createdProduct.Description,
                Price = createdProduct.Price,
                StockQuantity = createdProduct.StockQuantity,
                ImageUrl = createdProduct.ImageUrl,
                CreatedAt = createdProduct.CreatedAt,
                UpdatedAt = createdProduct.UpdatedAt,
                IsAvailable = createdProduct.IsAvailable,
                CategoryName = createdProduct.Category?.Name ?? "Unknown"
            };
            return CreatedAtAction(nameof(GetProductById), new { id = createdProduct.Id }, productDTO);
        }
        catch (ArgumentException ex)
        {
            _logger.LogError(ex, "创建产品时发生错误");
            return BadRequest(ex.Message);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "创建产品时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "创建产品时发生错误");
        }
    }

    /// <summary>
    /// 更新产品信息
    /// </summary>
    /// <param name="id">产品ID</param>
    /// <param name="product">更新的产品信息</param>
    /// <returns>更新后的产品</returns>
    [HttpPut("{id}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<ProductDTO>> UpdateProduct(int id, [FromBody] Product product)
    {
        if (id != product.Id)
        {
            return BadRequest("产品ID不匹配");
        }

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        try
        {
            var existingProduct = await _productService.GetByIdAsync(id);
            if (existingProduct == null)
            {
                return NotFound();
            }

            product.UpdatedAt = DateTime.UtcNow;
            var updatedProduct = await _productService.UpdateAsync(product);

            var productDTO = new ProductDTO
            {
                Id = updatedProduct.Id,
                Name = updatedProduct.Name,
                Description = updatedProduct.Description,
                Price = updatedProduct.Price,
                StockQuantity = updatedProduct.StockQuantity,
                ImageUrl = updatedProduct.ImageUrl,
                CreatedAt = updatedProduct.CreatedAt,
                UpdatedAt = updatedProduct.UpdatedAt,
                IsAvailable = updatedProduct.IsAvailable,
                CategoryName = updatedProduct.Category?.Name ?? "Unknown"
            };
            return Ok(productDTO);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新产品信息时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "更新产品信息时发生错误");
        }
    }

    /// <summary>
    /// 删除产品
    /// </summary>
    /// <param name="id">产品ID</param>
    /// <returns>删除结果</returns>
    [HttpDelete("{id}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> DeleteProduct(int id)
    {
        try
        {
            var product = await _productService.GetByIdAsync(id);
            if (product == null)
            {
                return NotFound();
            }

            await _productService.DeleteAsync(id);
            return NoContent();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "删除产品时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "删除产品时发生错误");
        }
    }

    /// <summary>
    /// 根据类别获取产品
    /// </summary>
    /// <param name="categoryId">类别ID</param>
    /// <returns>该类别下的产品列表</returns>
    [HttpGet("category/{categoryId}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult<IEnumerable<ProductDTO>>> GetProductsByCategory(int categoryId)
    {
        try
        {
            var products = await _productService.GetProductsByCategoryAsync(categoryId);
            var productDTOs = products.Select(product => new ProductDTO
            {
                Id = product.Id,
                Name = product.Name,
                Description = product.Description,
                Price = product.Price,
                StockQuantity = product.StockQuantity,
                ImageUrl = product.ImageUrl,
                CreatedAt = product.CreatedAt,
                UpdatedAt = product.UpdatedAt,
                IsAvailable = product.IsAvailable,
                CategoryName = product.Category?.Name ?? "Unknown"
            });
            return Ok(productDTOs);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据类别获取产品时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "根据类别获取产品时发生错误");
        }
    }

    /// <summary>
    /// 获取可用产品
    /// </summary>
    /// <returns>可用产品列表</returns>
    [HttpGet("available")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult<IEnumerable<ProductDTO>>> GetAvailableProducts()
    {
        try
        {
            var availableProducts = await _productService.GetAvailableProductsAsync();
            var productDTOs = availableProducts.Select(product => new ProductDTO
            {
                Id = product.Id,
                Name = product.Name,
                Description = product.Description,
                Price = product.Price,
                StockQuantity = product.StockQuantity,
                ImageUrl = product.ImageUrl,
                CreatedAt = product.CreatedAt,
                UpdatedAt = product.UpdatedAt,
                IsAvailable = product.IsAvailable,
                CategoryName = product.Category?.Name ?? "Unknown"
            });
            return Ok(productDTOs);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取可用产品时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "获取可用产品时发生错误");
        }
    }

    /// <summary>
    /// 根据价格范围获取产品
    /// </summary>
    /// <param name="minPrice">最低价格</param>
    /// <param name="maxPrice">最高价格</param>
    /// <returns>价格范围内的产品列表</returns>
    [HttpGet("price-range")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult<IEnumerable<ProductDTO>>> GetProductsByPriceRange([FromQuery] decimal minPrice, [FromQuery] decimal maxPrice)
    {
        try
        {
            var products = await _productService.GetProductsByPriceRangeAsync(minPrice, maxPrice);
            var productDTOs = products.Select(product => new ProductDTO
            {
                Id = product.Id,
                Name = product.Name,
                Description = product.Description,
                Price = product.Price,
                StockQuantity = product.StockQuantity,
                ImageUrl = product.ImageUrl,
                CreatedAt = product.CreatedAt,
                UpdatedAt = product.UpdatedAt,
                IsAvailable = product.IsAvailable,
                CategoryName = product.Category?.Name ?? "Unknown"
            });
            return Ok(productDTOs);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据价格范围获取产品时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "根据价格范围获取产品时发生错误");
        }
    }

    /// <summary>
    /// 搜索产品
    /// </summary>
    /// <param name="keyword">搜索关键词</param>
    /// <returns>符合条件的产品列表</returns>
    [HttpGet("search")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult<IEnumerable<ProductDTO>>> SearchProducts([FromQuery] string keyword)
    {
        try
        {
            var products = await _productService.SearchProductsAsync(keyword);
            var productDTOs = products.Select(product => new ProductDTO
            {
                Id = product.Id,
                Name = product.Name,
                Description = product.Description,
                Price = product.Price,
                StockQuantity = product.StockQuantity,
                ImageUrl = product.ImageUrl,
                CreatedAt = product.CreatedAt,
                UpdatedAt = product.UpdatedAt,
                IsAvailable = product.IsAvailable,
                CategoryName = product.Category?.Name ?? "Unknown"
            });
            return Ok(productDTOs);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "搜索产品时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "搜索产品时发生错误");
        }
    }

    /// <summary>
    /// 更新产品库存
    /// </summary>
    /// <param name="id">产品ID</param>
    /// <param name="quantity">更新的库存数量</param>
    /// <returns>更新结果</returns>
    [HttpPatch("{id}/stock")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> UpdateProductStock(int id, [FromBody] int quantity)
    {
        if (quantity < 0)
        {
            return BadRequest("库存数量不能为负数");
        }

        try
        {
            await _productService.UpdateProductStockAsync(id, quantity);
            return Ok("库存更新成功");
        }
        catch (ArgumentException ex)
        {
            if (ex.Message == "产品不存在")
            {
                return NotFound(ex.Message);
            }
            _logger.LogError(ex, "更新产品库存时发生错误");
            return BadRequest(ex.Message);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新产品库存时发生错误");
            return StatusCode(StatusCodes.Status500InternalServerError, "更新产品库存时发生错误");
        }
    }
}